package pe.com.trestperu.common.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.springframework.util.CollectionUtils;

/**
 * 
 *
 * @author Telly Tataje
 *
 */
@SuppressWarnings("unchecked")
public class OrderedMap extends HashMap {
	private static final long serialVersionUID = 1L;
	List keys = new ArrayList();
	
	public OrderedMap(){
		super();
	}

	public OrderedMap(int initialCapacity){
		super(initialCapacity);
	}
	
	public static class KeySet extends HashSet{
		private static final long serialVersionUID = 1L;
		List keys;

		public Iterator iterator() {
			return keys.iterator();
		}
	}

	public Set keySet() {
		OrderedMap.KeySet msgKeySet = new KeySet();
		msgKeySet.addAll(super.keySet());
		msgKeySet.keys = this.keys;
		return msgKeySet;
	}

	public Object put(Object key, Object value) {
		if(!CollectionUtils.containsInstance(keys, key)){
			keys.add(key);
		}
		return super.put(key, value);
	}

    /**
     * Returns a {@link Collection} view of the values contained in this map.
     * The collection is backed by the map, so changes to the map are
     * reflected in the collection, and vice-versa.  If the map is
     * modified while an iteration over the collection is in progress
     * (except through the iterator's own <tt>remove</tt> operation),
     * the results of the iteration are undefined.  The collection
     * supports element removal, which removes the corresponding
     * mapping from the map, via the <tt>Iterator.remove</tt>,
     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
     * <tt>retainAll</tt> and <tt>clear</tt> operations.  It does not
     * support the <tt>add</tt> or <tt>addAll</tt> operations.
     */
    public Collection values() {
        List vs = new ArrayList();
        for(int i = 0; i < keys.size(); i++){
        	vs.add(super.get(keys.get(i)));
        }
        return vs;
    }
}
